package com.cheer.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.dao.AdminDao;
import com.cheer.dao.OrganizationDao;
import com.cheer.dto.AccountDTO;
import com.cheer.dto.AdminImportDTO;
import com.cheer.dto.AdminPageDTO;
import com.cheer.dto.AdminSaveDTO;
import com.cheer.entity.*;
import com.cheer.enums.*;
import com.cheer.exception.ServiceException;
import com.cheer.manager.AccountManager;
import com.cheer.security.UserInfoHolder;
import com.cheer.service.*;
import com.cheer.util.FileUtil;
import com.cheer.vo.AdminVO;
import com.cheer.vo.Page;
import com.cheer.param.ApplicantSpecialParam;
import com.cheer.vo.ReferencePlacesTswVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class AdminServiceImpl extends ServiceImpl<AdminDao, Admin> implements AdminService {

    @Autowired
    private OrganizationDao organizationDao;

    @Autowired
    private AdminDao adminDao;

    @Autowired
    private AccountManager accountManager;

    @Autowired
    private ApplicantService applicantService;

    @Autowired
    private ReferencePlacesService referencePlacesService;

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private ReferenceSpecialService referenceSpecialService;

    @Autowired
    private StandingBookService standingBookService;


    @Override
    public Page<AdminVO> getPage(Integer pageNum, Integer pageSize, Long orgId, String orgName, String contactPerson) {
        // 参数处理
        Organization organization = organizationDao.selectById(orgId);
        if (organization == null) {
            return null;
        }
        orgName = StringUtils.trimToNull(orgName);
        contactPerson = StringUtils.trimToNull(contactPerson);
        // 分页查询
        PageHelper.startPage(pageNum, pageSize);
        List<AdminPageDTO> adminDTOS = adminDao.listPage(organization.getOrgPath(), orgName, contactPerson);
        PageInfo<AdminPageDTO> pageInfo = new PageInfo<>(adminDTOS);
        // 返回数据处理
        List<AdminVO> adminVOS = adminDTOS.stream().map(AdminPageDTO::build).collect(Collectors.toList());
        return new Page<AdminVO>().setPageNum(pageInfo.getPageNum())
                .setPageSize(pageInfo.getPageSize())
                .setPages(pageInfo.getPages())
                .setTotal(pageInfo.getTotal())
                .setContent(adminVOS);
    }

    @Override
    @Transactional
    public void add(AdminSaveDTO adminSaveDTO) {
        // 校验参数
        if (!StringUtils.equals(adminSaveDTO.getPassword(), adminSaveDTO.getConfirmPassword())) {
            throw new ServiceException("两次密码输入不一致");
        }
        Organization organization = organizationDao.selectById(adminSaveDTO.getOrgId());
        if (organization == null) {
            throw new ServiceException("组织机构不存在");
        }
        if (organization.getCategory()) {
            throw new ServiceException("组织机构不可选");
        }
        // 创建账号
        AccountDTO accountDTO = adminSaveDTO.build(organization.getOrgRole());
        Long accountId = accountManager.saveAccount(accountDTO);
        // 创建管理员
        Admin admin = adminSaveDTO.build(accountId, organization);
        adminDao.insert(admin);
        // 刷新名额表
        referencePlacesService.createPlaces();
    }

    @Override
    public void reset(Long adminId) {
        Admin admin = adminDao.selectById(adminId);
        if (admin == null) {
            throw new ServiceException("管理员用户已失效");
        }
        accountManager.resetPassword(admin.getAccountId());
    }

    @Override
    @Transactional
    public void delete(List<Long> adminIds) {
        if (CollectionUtils.isEmpty(adminIds)) {
            return;
        }
        List<Admin> admins = adminDao.selectBatchIds(adminIds);
        if (CollectionUtils.isEmpty(admins)) {
            return;
        }

        List<Long> accountIds = admins.stream().map(Admin::getAccountId).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(accountIds)) {
            accountManager.deleteByIds(accountIds);
        }
        adminDao.deleteBatchIds(adminIds);
    }

    @Override
    @Transactional
    public void importAdmin(Long orgId, MultipartFile file) {
        // 校验机构
        Organization organization = organizationDao.selectById(orgId);
        if (organization == null) {
            throw new ServiceException("您所在的组织机构已失效");
        }
        // 读取文件
        FileUtil.checkFile(file, "xlsx");
        List<AdminImportDTO> importAdmins;
        try (ExcelReader reader = ExcelUtil.getReader(file.getInputStream())) {
            reader.setHeaderAlias(AdminImportDTO.getHeaderAlias());
            importAdmins = reader.read(0, 1, AdminImportDTO.class);
        } catch (IOException e) {
            log.error("读取文件异常：" + e.getMessage(), e);
            throw new ServiceException("读取文件异常");
        }
        // 验证文件数据
        if (CollectionUtil.isEmpty(importAdmins)) {
            throw new ServiceException("上传文件无效，请检查文件内容");
        }
        for (int i = 0; i < importAdmins.size(); i++) {
            importAdmins.get(i).check(i + 1);
        }
        // 查询机构
        List<Organization> organizations = organizationDao.listByOrgPath(organization.getOrgPath());
        Map<String, List<Organization>> orgMap = organizations.stream()
                .collect(Collectors.groupingBy(Organization::getOrgName));
        // 创建账号
        for (AdminImportDTO importAdmin : importAdmins) {
            // 匹配组织机构
            if (!orgMap.containsKey(importAdmin.getOrgName())) {
                continue;
            }
            List<Organization> matchedOrganizations = orgMap.get(importAdmin.getOrgName()).stream()
                    .filter(org -> !org.getCategory())
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(matchedOrganizations)) {
                continue;
            }
            Organization matchedOrg = matchedOrganizations.get(0);
            // 创建账号
            AccountDTO accountDTO = importAdmin.build(matchedOrg);
            Long accountId = accountManager.saveAccount(accountDTO);
            // 创建管理员
            Admin admin = importAdmin.build(accountId, matchedOrg);
            adminDao.insert(admin);
        }
    }

    @Override
    @Transactional
    public void specialRecommend(ApplicantSpecialParam specialApplicantVO) {

        Integer role = userInfoHolder.getAccount().getRole();
        // 市地团委 下属单位团委 每年只能推荐一个
        if(role == RoleEnum.SECOND_ADMIN.getCode()
                || role == RoleEnum.LOWER_ADMIN.getCode()){
            Long accountId = userInfoHolder.getAccountId();
            ReferenceSpecialEntity referenceSpecialEntity = referenceSpecialService.listByAccountId(accountId, DateUtil.format(new Date(), "yyyy"));
            if(referenceSpecialEntity != null){
                throw new ServiceException("当前账号推荐名额已满！");
            }
        }
        // 校验参数
        if (!StringUtils.equals(specialApplicantVO.getPassword(), specialApplicantVO.getConfirmPassword())) {
            throw new ServiceException("两次密码输入不一致");
        }
        Organization organization = organizationDao.selectById(specialApplicantVO.getOrgId());
        if (organization == null) {
            throw new ServiceException("组织机构不存在");
        }
        if (organization.getCategory()) {
            throw new ServiceException("组织机构不可选");
        }
        // 申报为集体
        AccountDTO accountDTO = specialApplicantVO.build(RoleEnum.APPLICANT.getCode());
        Long accountId = accountManager.saveAccount(accountDTO);

        // 创建集体账号
        Applicant applicant = new Applicant();
        applicant.setAccountId(accountId);
        applicant.setApplicantName(specialApplicantVO.getApplicantName());
        applicant.setContactPerson(specialApplicantVO.getPhone());
        applicant.setContactPersonPhone(specialApplicantVO.getPhone());
        applicant.setRegisterStatus(RegisterStatusEnum.CITY_TITLE.getCode());
        applicant.setTitle(TitleEnum.NO.getType());
        applicant.setRegisterTitle(TitleEnum.NO.getType());
        applicant.setOrgId(specialApplicantVO.getOrgId());
        applicant.setRegisterTitle(TitleEnum.PROVINCE.getType());
        applicant.setOrgPath(organization.getOrgPath());
        applicant.setContactPersonBirth(new Date());
        applicantService.save(applicant);
        // 创建特殊推荐账号
        // referenceService.createSpecial(accountId, applicant.getId(), specialApplicantVO.getOrgId(), organization.getOrgPath());
        // 创建台账信息
        StandingBook standingBook = new StandingBook();
        standingBook.setReviewStatus(ReviewStatusEnum.TO_REVIEW.getCode());
        standingBook.setAchievement("");
        standingBook.setAward("");
        standingBook.setAccountId(accountId);

        standingBookService.save(standingBook);
    }


}
